From 8f4943102b878b10d196a6222d31083f414e91b5 Mon Sep 17 00:00:00 2001 From: "arun.sharma@intel.com[kaf24]" Date: Thu, 30 Jun 2005 08:07:49 +0000 Subject: [PATCH] bitkeeper revision 1.1774 (42c3a855yAuKBfmJfftjhiVDml26pg) [PATCH] Extend the VMX intercept mechanism to include mmio as well as portio. Extend the VMX intercept mechanism to include mmio as well as portio. Signed-off-by: Yunhong Jiang Signed-off-by: Xiaofeng Ling Signed-off-by: Arun Sharma --- xen/arch/x86/vmx.c | 12 +++++----- xen/arch/x86/vmx_intercept.c | 13 +++++++---- xen/arch/x86/vmx_platform.c | 13 ++++++----- xen/include/asm-x86/vmx_intercept.h | 34 +++++++++++++++++++++++++---- xen/include/asm-x86/vmx_platform.h | 1 + 5 files changed, 54 insertions(+), 19 deletions(-) diff --git a/xen/arch/x86/vmx.c b/xen/arch/x86/vmx.c index 8717d4bea0..686bd36969 100644 --- a/xen/arch/x86/vmx.c +++ b/xen/arch/x86/vmx.c @@ -135,17 +135,20 @@ static int vmx_do_page_fault(unsigned long va, struct cpu_user_regs *regs) } #endif - if (!vmx_paging_enabled(current)) + if (!vmx_paging_enabled(current)){ handle_mmio(va, va); - + return 1; + } gpte = gva_to_gpte(va); if (!(l1e_get_flags(gpte) & _PAGE_PRESENT) ) return 0; gpa = l1e_get_paddr(gpte) + (va & ~PAGE_MASK); /* Use 1:1 page table to identify MMIO address space */ - if (mmio_space(gpa)) + if (mmio_space(gpa)){ handle_mmio(va, gpa); + return 1; + } result = shadow_fault(va, regs); @@ -451,10 +454,9 @@ static void vmx_io_instruction(struct cpu_user_regs *regs, p->port_mm = 0; /* Check if the packet needs to be intercepted */ - if (vmx_io_intercept(p)) { + if (vmx_portio_intercept(p)) /* no blocking & no evtchn notification */ return; - } set_bit(ARCH_VMX_IO_WAIT, &d->arch.arch_vmx.flags); p->state = STATE_IOREQ_READY; diff --git a/xen/arch/x86/vmx_intercept.c b/xen/arch/x86/vmx_intercept.c index b6b0fffe70..1ed715ffcc 100644 --- a/xen/arch/x86/vmx_intercept.c +++ b/xen/arch/x86/vmx_intercept.c @@ -31,14 +31,17 @@ #ifdef CONFIG_VMX -/* for intercepting io request after vm_exit, return value: 0--not handle; 1--handled */ -int vmx_io_intercept(ioreq_t *p) +/* Check if the request is handled inside xen + return value: 0 --not handled; 1 --handled */ +int vmx_io_intercept(ioreq_t *p, int type) { struct vcpu *d = current; struct vmx_handler_t *handler = &(d->domain->arch.vmx_platform.vmx_handler); int i; unsigned long addr, offset; for (i = 0; i < handler->num_slot; i++) { + if( type != handler->hdl_list[i].type) + continue; addr = handler->hdl_list[i].addr; offset = handler->hdl_list[i].offset; if (p->addr >= addr && @@ -48,7 +51,8 @@ int vmx_io_intercept(ioreq_t *p) return 0; } -int register_io_handler(unsigned long addr, unsigned long offset, intercept_action_t action) +int register_io_handler(unsigned long addr, unsigned long offset, + intercept_action_t action, int type) { struct vcpu *d = current; struct vmx_handler_t *handler = &(d->domain->arch.vmx_platform.vmx_handler); @@ -62,6 +66,7 @@ int register_io_handler(unsigned long addr, unsigned long offset, intercept_acti handler->hdl_list[num].addr = addr; handler->hdl_list[num].offset = offset; handler->hdl_list[num].action = action; + handler->hdl_list[num].type = type; handler->num_slot++; return 1; @@ -262,7 +267,7 @@ void vmx_hooks_assist(struct vcpu *d) p->state = STATE_IORESP_READY; /* register handler to intercept the PIT io when vm_exit */ - register_io_handler(0x40, 4, intercept_pit_io); + register_portio_handler(0x40, 4, intercept_pit_io); } } diff --git a/xen/arch/x86/vmx_platform.c b/xen/arch/x86/vmx_platform.c index 9ec14c8c8e..c2f7cd740f 100644 --- a/xen/arch/x86/vmx_platform.c +++ b/xen/arch/x86/vmx_platform.c @@ -606,12 +606,11 @@ static void send_mmio_req(unsigned long gpa, if ((pvalid) && vmx_paging_enabled(current)) p->u.pdata = (void *) gva_to_gpa(p->u.data); -#if 0 - printf("send_mmio_req: eip 0x%lx:0x%lx, dir %d, pdata_valid %d, ", - inst_decoder_regs->cs, inst_decoder_regs->eip, p->dir, p->pdata_valid); - printf("port_mm %d, size %lld, addr 0x%llx, value 0x%lx, count %lld\n", - p->port_mm, p->size, p->addr, value, p->count); -#endif + if (vmx_mmio_intercept(p)){ + p->state = STATE_IORESP_READY; + vmx_io_assist(d); + return; + } evtchn_send(iopacket_port(d->domain)); vmx_wait_io(); @@ -709,6 +708,7 @@ void handle_mmio(unsigned long va, unsigned long gpa) // Send the request and waiting for return value. mpci_p->mmio_target = mmio_inst.operand[1]; send_mmio_req(gpa, &mmio_inst, value, IOREQ_READ, 0); + return; } else { // Write to MMIO if (mmio_inst.operand[0] & IMMEDIATE) { @@ -728,6 +728,7 @@ void handle_mmio(unsigned long va, unsigned long gpa) if (!strncmp((char *)mmio_inst.i_name, "stos", 4)) { send_mmio_req(gpa, &mmio_inst, inst_decoder_regs->eax, IOREQ_WRITE, 0); + return; } domain_crash_synchronous(); diff --git a/xen/include/asm-x86/vmx_intercept.h b/xen/include/asm-x86/vmx_intercept.h index 9687f8cdec..ab54682b2a 100644 --- a/xen/include/asm-x86/vmx_intercept.h +++ b/xen/include/asm-x86/vmx_intercept.h @@ -1,4 +1,3 @@ - #ifndef _VMX_INTERCEPT_H #define _VMX_INTERCEPT_H @@ -13,18 +12,45 @@ typedef int (*intercept_action_t)(ioreq_t*); +enum {PORTIO, MMIO}; + struct vmx_handler_t { int num_slot; struct { unsigned long addr; + int type; unsigned long offset; intercept_action_t action; } hdl_list[MAX_IO_HANDLER]; }; /* global io interception point in HV */ -extern int vmx_io_intercept(ioreq_t*); -extern int register_io_handler(unsigned long, unsigned long, intercept_action_t); - +extern int vmx_io_intercept(ioreq_t *p, int type); +extern int register_io_handler(unsigned long addr, unsigned long offset, + intercept_action_t action, int type); + +static inline int vmx_portio_intercept(ioreq_t *p) +{ + return vmx_io_intercept(p, PORTIO); +} + +static inline int vmx_mmio_intercept(ioreq_t *p) +{ + return vmx_io_intercept(p, MMIO); +} + +static inline int register_portio_handler(unsigned long addr, + unsigned long offset, + intercept_action_t action) +{ + return register_io_handler(addr, offset, action, PORTIO); +} + +static inline int register_mmio_handler(unsigned long addr, + unsigned long offset, + intercept_action_t action) +{ + return register_io_handler(addr, offset, action, MMIO); +} #endif /* _VMX_INTERCEPT_H */ diff --git a/xen/include/asm-x86/vmx_platform.h b/xen/include/asm-x86/vmx_platform.h index 4a388d1c81..31fb44ae33 100644 --- a/xen/include/asm-x86/vmx_platform.h +++ b/xen/include/asm-x86/vmx_platform.h @@ -88,6 +88,7 @@ struct virtual_platform_def { extern void handle_mmio(unsigned long, unsigned long); extern void vmx_wait_io(void); extern int vmx_setup_platform(struct vcpu *, struct cpu_user_regs *); +extern void vmx_io_assist(struct vcpu *v); // XXX - think about this -- maybe use bit 30 of the mfn to signify an MMIO frame. #define mmio_space(gpa) (!VALID_MFN(phys_to_machine_mapping((gpa) >> PAGE_SHIFT))) -- 2.30.2